package com.zjw.zy.voice;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.IBinder;
import android.view.View;
import android.widget.RemoteViews;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;

import com.zjw.zy.R;
import com.zjw.zy.bean.WsMessage;
import com.zjw.zy.constant.C2CMessageInfo;
import com.zjw.zy.service.helper.WbSocketHelper;
import com.zjw.zy.smi.JustWithIt;
import com.zjw.zy.utils.AppUtils;
import com.zjw.zy.utils.LogUtils;
import com.zjw.zy.utils.PermissionUtils;
import com.zjw.zy.utils.TimeUtils;
import com.zjw.zy.utils.taskpool.TaskPool;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import remotecall.RemoteCallManager;
import remotecall.call.IRemoteCall;
import remotecall.call.WithIt;

/**
 * @author ：zhong.jw
 * @date ：Created in 2022/12/12 15:17
 * <p>
 * 语音通话前台服务
 */
public class VoiceService extends Service {

    public static final String VOICE_CHANNEL_ID = "VOICE_CHANNEL_ID";

    public static final String SERVICE_ACTION = "com.zjw.zy.service.VOICE_SERVICE";
    private static final int VOICE_NOTIFICATION_ID = 1;

    private static final String TAG = "VoiceService";

    public static final String CONNECT_TYPE = "CONNECT_TYPE";
    public static final int CONNECT_SENDER_TYPE = 1;
    public static final int CONNECT_REPAIR_TYPE = 2;
    //action
    private static final String ACTION_CLICK_ACCEPT = "com.zjw.zy.ACTION_CLICK_ACCEPT";
    private static final String ACTION_CLICK_REJECT = "com.zjw.zy.ACTION_CLICK_REJECT";
    private static final String ACTION_CLICK_CLOSE = "com.zjw.zy.ACTION_CLICK_CLOSE";
    private static final String ACTION_CLICK_CANCEL = "com.zjw.zy.ACTION_CLICK_CANCEL";


    //采集频率
    private static final int AUDIO_SAMPLE_RATE = 16000;
    private static final int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_MONO;
    private static final int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
    private static final int AUDIO_INPUT = MediaRecorder.AudioSource.VOICE_COMMUNICATION;


    //几种通知的ui
    private volatile int currentUiMode;
    private static final int UI_MODE_UN_KNOW = -1;
    private static final int UI_MODE_CONNECT = 1;
    private static final int UI_MODE_CLOSE = 2;
    private static final int UI_MODE_REJECT = 3;

    private volatile Disposable timeDisposable;

    private volatile AudioRecord audioRecord;

    private volatile AudioTrack audioTrack;

    private volatile boolean isConnect = false;

    //消息处理类
    private final IRemoteCall<WsMessage> traceCall = RemoteCallManager.defaultImpl().remoteCall(obj -> {
        String info = obj.getInfo();

        if (info.endsWith(C2CMessageInfo.VOICE_CONNECT_CLOSE)) {
            uiMode(UI_MODE_CLOSE);
            stopWechat();
            return;
        }

        if (info.endsWith(C2CMessageInfo.VOICE_CONNECT_REJECT)) {
            uiMode(UI_MODE_REJECT);
            return;
        }

        if (info.endsWith(C2CMessageInfo.VOICE_CONNECT_ACCEPT)) {
            //建立连接
            uiMode(UI_MODE_CONNECT);
            startWechat();
            return;
        }

        if (info.endsWith(C2CMessageInfo.VOICE_CONNECT_ITEM)) {
            TaskPool.voiceReceive().post(() -> {
                if (audioTrack != null && isConnect) {
                    byte[] bytes = obj.castPayload(byte[].class);
                    audioTrack.write(bytes, 0, bytes.length);
                }
            });
        }
    });


    private static final int REQUEST_VOICE_CONNECT = 1;


    private RemoteViews remoteViews;


    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (remoteViews == null) {
                LogUtils.d(TAG, "remoteViews == null");
                return;
            }
            String action = intent.getAction();
            switch (action) {
                case ACTION_CLICK_ACCEPT:
                    performClickAccept();
                    break;

                case ACTION_CLICK_REJECT:
                    performClickReject();
                    break;

                case ACTION_CLICK_CLOSE:
                    performClickClose();
                    break;

                case ACTION_CLICK_CANCEL:
                    performClickCancel();
                    break;
            }
        }
    };


    private Notification mNotification;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //连接类型
        int connectType = intent.getIntExtra(CONNECT_TYPE, CONNECT_REPAIR_TYPE);

        mNotification = (connectType == CONNECT_SENDER_TYPE ? createSenderNotification()
                : createRepairNotification());
        //启动前台服务
        startForeground(VOICE_NOTIFICATION_ID, mNotification);

        WbSocketHelper.getInstance().registerMessageObserver(traceCall);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        initReceiver();
    }

    private void initReceiver() {

        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_CLICK_ACCEPT);
        filter.addAction(ACTION_CLICK_REJECT);
        filter.addAction(ACTION_CLICK_CLOSE);
        filter.addAction(ACTION_CLICK_CANCEL);
        registerReceiver(receiver, filter);
    }

    private void performClickClose() {
        WbSocketHelper.getInstance().sendMessage(WsMessage.obtainC2C(C2CMessageInfo.VOICE_CONNECT_CLOSE));
        uiMode(UI_MODE_CLOSE);
        stopWechat();
    }

    private void performClickCancel() {
        WbSocketHelper.getInstance().sendMessage(WsMessage.obtainC2C(C2CMessageInfo.VOICE_CONNECT_CLOSE));
        uiMode(UI_MODE_CLOSE);
    }

    private void exitService() {
        stopForeground(true);
        stopWechat();
        stopSelf();
    }

    private void performClickReject() {
        WbSocketHelper.getInstance().sendMessage(WsMessage.obtainC2C(C2CMessageInfo.VOICE_CONNECT_REJECT));
        uiMode(UI_MODE_REJECT);
    }

    private void performClickAccept() {
        uiMode(UI_MODE_CONNECT);
        WbSocketHelper.getInstance().sendMessage(WsMessage.obtainC2C(C2CMessageInfo.VOICE_CONNECT_ACCEPT));
        startWechat();
    }

    /**
     * 创建接收者notify
     */
    private Notification createRepairNotification() {

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, VOICE_CHANNEL_ID);


        builder.setAutoCancel(false);
        builder.setSmallIcon(R.drawable.icon_telephone);
        builder.setContentTitle("测试服务");

        //remote view

        remoteViews = new RemoteViews(getPackageName(), R.layout.voice_foreground_layout);


        //发起服务
        Intent intent = new Intent(ACTION_CLICK_ACCEPT);
        intent.setPackage(getPackageName());
        remoteViews.setOnClickPendingIntent(R.id.voice_remote_accept, PendingIntent.getBroadcast(
                this,
                REQUEST_VOICE_CONNECT,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        ));

        Intent intent2 = new Intent(ACTION_CLICK_REJECT);
        intent2.setPackage(getPackageName());
        remoteViews.setOnClickPendingIntent(R.id.voice_remote_reject, PendingIntent.getBroadcast(
                this,
                REQUEST_VOICE_CONNECT,
                intent2,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        ));

        builder.setContent(remoteViews);
        builder.setOnlyAlertOnce(true);

        return builder.build();
    }


    private Notification createSenderNotification() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, VOICE_CHANNEL_ID);


        builder.setAutoCancel(false);
        builder.setSmallIcon(R.drawable.icon_telephone);
        builder.setContentTitle("测试服务");

        //remote view
        remoteViews = new RemoteViews(getPackageName(), R.layout.voice_foreground_layout);
        remoteViews.setTextViewText(R.id.voice_remote_title, "正呼叫亲爱哒...");
        remoteViews.setTextViewText(R.id.voice_remote_reject, "取消");
        remoteViews.setViewVisibility(R.id.voice_remote_accept, View.GONE);

        //发起服务
        Intent intent = new Intent(ACTION_CLICK_CANCEL);
        intent.setPackage(getPackageName());
        remoteViews.setOnClickPendingIntent(R.id.voice_remote_reject, PendingIntent.getBroadcast(
                this,
                REQUEST_VOICE_CONNECT,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        ));

        builder.setContent(remoteViews);
        builder.setOnlyAlertOnce(true);
        return builder.build();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {


        return null;
    }


    @Override
    public void onDestroy() {
        stopForeground(true);

        unregisterReceiver(receiver);

        exitService();

        WbSocketHelper.getInstance().unregisterMessageObserver(traceCall);
        super.onDestroy();
    }


    public void startWechat() {
        TaskPool.main().postDelayed(() -> {
            LogUtils.d(TAG, "startWechat() called");
            isConnect = true;
            try {
                int minBufferSize1 = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING);

                if (ActivityCompat.checkSelfPermission(AppUtils.getApp(), android.Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
                    audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, minBufferSize1);
                    audioRecord.startRecording();

                    int minBufferSize2 = AudioTrack.getMinBufferSize(AUDIO_SAMPLE_RATE, AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, AUDIO_ENCODING);
                    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, AUDIO_SAMPLE_RATE, AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, AUDIO_ENCODING, minBufferSize2, AudioTrack.MODE_STREAM);
                    //开始播放
                    audioTrack.play();


                    WsMessage wsMessage = new WsMessage();
                    wsMessage.setFrom(AppUtils.getSelfAccess());
                    wsMessage.setTo(AppUtils.getLoveAccess());
                    wsMessage.setInfo(WsMessage.CLIENT_TO_CLIENT_INFO + C2CMessageInfo.VOICE_CONNECT_ITEM);

                    TaskPool.voiceSend().post(() -> {
                        byte[] audioData = new byte[1024];
                        //采集数据
                        while (isConnect) {
                            int code = audioRecord.read(audioData, 0, audioData.length);
                            if (code >= 0) {
                                LogUtils.d(TAG, "send bytes");
                                wsMessage.setPayload(audioData);
                                wsMessage.jsonPayload();
                                WbSocketHelper.getInstance().sendMessage(wsMessage);
                            }
                        }

                        LogUtils.d(TAG, "exit voiceSend");
                    });
                } else {
                    PermissionUtils.toastNotAccessPermission();
                }
            } catch (Exception ignore) {
                isConnect = false;
            }
        }, 1000);
    }


    private void stopWechat() {
        LogUtils.d(TAG, "stopWechat() called");
        isConnect = false;
        try {
            if (audioRecord != null) {
                audioRecord.startRecording();
                audioRecord.stop();
                audioRecord.release();
                audioRecord = null;
            }

            if (audioTrack != null) {
                audioTrack.stop();
                audioTrack.release();
                audioTrack = null;
            }
        } catch (Exception ignore) {

        }
    }


    private void uiMode(int uiMode) {
        final NotificationManager notificationManager = getSystemService(NotificationManager.class);
        currentUiMode = uiMode;
        switch (uiMode) {
            case UI_MODE_CONNECT:
                if (mNotification != null) {
                    remoteViews.setViewVisibility(R.id.voice_remote_accept, View.GONE);
                    remoteViews.setViewVisibility(R.id.voice_remote_connect_time, View.VISIBLE);
                    remoteViews.setTextViewText(R.id.voice_remote_reject, "挂断");
                    remoteViews.setTextViewText(R.id.voice_remote_title, "已接通亲爱哒");
                    Intent intent = new Intent(ACTION_CLICK_CLOSE);
                    intent.setPackage(getPackageName());
                    remoteViews.setOnClickPendingIntent(R.id.voice_remote_reject, PendingIntent.getBroadcast(this,
                            REQUEST_VOICE_CONNECT,
                            intent,
                            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));

                    notificationManager.notify(VOICE_NOTIFICATION_ID, mNotification);

                    timeDisposable = Observable.interval(0, 1, TimeUnit.SECONDS).subscribe(second -> {
                        remoteViews.setTextViewText(R.id.voice_remote_connect_time, formatConnectTime(second));
                        notificationManager.notify(VOICE_NOTIFICATION_ID, mNotification);
                    });
                }
                break;


            case UI_MODE_CLOSE:
                if (timeDisposable != null) {
                    timeDisposable.dispose();
                    timeDisposable = null;
                }
                remoteViews.setTextViewText(R.id.voice_remote_title, "已挂断");
                remoteViews.setViewVisibility(R.id.voice_remote_reject, View.GONE);
                remoteViews.setViewVisibility(R.id.voice_remote_accept, View.GONE);
                notificationManager.notify(VOICE_NOTIFICATION_ID, mNotification);
                TaskPool.main().postDelayed(this::exitService, 2000L);
                break;

            case UI_MODE_REJECT:
                if (timeDisposable != null) {
                    timeDisposable.dispose();
                    timeDisposable = null;
                }
                remoteViews.setTextViewText(R.id.voice_remote_title, "已拒绝");
                remoteViews.setViewVisibility(R.id.voice_remote_reject, View.GONE);
                remoteViews.setViewVisibility(R.id.voice_remote_accept, View.GONE);
                notificationManager.notify(VOICE_NOTIFICATION_ID, mNotification);
                TaskPool.main().postDelayed(this::exitService, 2000L);
                break;

            default:
                currentUiMode = UI_MODE_UN_KNOW;
        }
    }

    private String formatConnectTime(Long second) {
        if (second == null) {
            return "00:00:00";
        }

        long hour = second / 60 % 60;
        long minute = second / 60;
        long s = second % 60;

        return TimeUtils.adjustTime((int) hour) + ":"
                + TimeUtils.adjustTime((int) minute)
                + ":" + TimeUtils.adjustTime((int) s);
    }
}
